/**
 * 发布订阅
 */
class EventEmitter {
    handlers = {}

    on(type, handler, once = false) {
        if (!this.handlers[type]) {
            this.handlers[type] = []
        }
        if (!this.handlers[type].includes(handler)) {
            this.handlers[type].push(handler)

            handler.once = once
        }
    }

    once(type, handler) {
        this.on(type, handler, true)
    }

    off(type, handler) {
        if (this.handlers[type]) {
            this.handlers[type] = this.handlers[type].filter(h => h !== handler)
        }
    }

    trigger(type, ...args) {
        if (this.handlers[type]) {
            this.handlers[type].forEach(handler => {
                handler.apply(this, args)
                if (handler.once) {
                    this.off(type, handler)
                }
            })
        }
    }
}

const ev = new EventEmitter()

function handler1() {
    console.log('handler1')
}
function handler2() {
    console.log('handler2')
}
function handler3() {
    console.log('handler3')
}

ev.on('test', handler1)
ev.once('test', handler2)
ev.on('test', handler3)

ev.trigger('test')
ev.trigger('test')
